package com.itheima.common;

/**
 * @author tang
 * @date 2022/11/21 20:47
 */

import com.itheima.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDateTime;


@Slf4j
@Component
@Aspect
public class MyAdvice {

    //设置切入点
    //1.add切入点
    @Pointcut("execution(* com.itheima.controller.EmployeeController.add(..))")
    public void addPointcut() {
    }

    //2.CategoryAdd切入点
    @Pointcut("execution(* com.itheima.controller.CategoryController.add(..))")
    public void CategoryAddPointcut() {
    }

    //1.2update方法切入点
    @Pointcut("execution(* com.itheima.controller.*.edit*(..))")
    public void updatePointScut() {
    }

    //员工字段填充
    @Before("addPointcut()")
    public void doAddBefore(JoinPoint joinPoint) {
        log.info("字段填充执行");

        //获得目标方法的参数信息
        Object[] args = joinPoint.getArgs(); //getArgs()获得传入方法的参数对象
//        Employee employee = (Employee) args[0];
        Class<?> aClass = args[0].getClass();
        //通过反射获得对象的set方法
        Method setId;
        Method setPassword;
        Method setStatus;
        Method setCreateTime;
        Method setUpdateTime;
        Method setUpdateUser;
        Method setCreateUser;
        try {
            setId = aClass.getDeclaredMethod("setId", Long.class);
            setPassword = aClass.getDeclaredMethod("setPassword", String.class);
            setStatus = aClass.getDeclaredMethod("setStatus", Integer.class);
            setCreateTime = aClass.getDeclaredMethod("setCreateTime", LocalDateTime.class);
            setUpdateTime = aClass.getDeclaredMethod("setUpdateTime", LocalDateTime.class);
            setUpdateUser = aClass.getDeclaredMethod("setUpdateUser", Long.class);
            setCreateUser = aClass.getDeclaredMethod("setCreateUser", Long.class);
        } catch (NoSuchMethodException e) {
            throw new CustomException("获得反射方法失败");
        }
        //雪花算法生成id
        IdWorker idWorker = new IdWorker(0, 0);

        //获得当前登录用户的的id
        Long currentId = BaseContext.getCurrentId();

        //获得参数对象
        Object arg = args[0];

        //执行反射执行方法
        try {
            setId.invoke(arg, idWorker.nextId());
            setCreateTime.invoke(arg, LocalDateTime.now());
            setPassword.invoke(arg, "123456");
            setStatus.invoke(arg, 1);
            setUpdateTime.invoke(arg, LocalDateTime.now());
            setUpdateUser.invoke(arg, currentId);
            setCreateUser.invoke(arg, currentId);
        } catch (Exception e) {
            throw new CustomException("反射执行方法失败");
        }
    }

    //分类字段填充
    @Before("CategoryAddPointcut()")
    public void doCategoryAddBefore(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        Class<?> aClass = args[0].getClass();
        Method setId;
        Method setCreateTime;
        Method setUpdateTime;
        Method setUpdateUser;
        Method setCreateUser;
        try {
            setId = aClass.getDeclaredMethod("setId", Long.class);
            setCreateTime = aClass.getDeclaredMethod("setCreateTime", LocalDateTime.class);
            setUpdateTime = aClass.getDeclaredMethod("setUpdateTime", LocalDateTime.class);
            setUpdateUser = aClass.getDeclaredMethod("setUpdateUser", Long.class);
            setCreateUser = aClass.getDeclaredMethod("setCreateUser", Long.class);
        } catch (NoSuchMethodException e) {
            throw new CustomException("获得反射方法失败");
        }
        //雪花算法生成id
        IdWorker idWorker = new IdWorker(0, 0);

        //获得当前登录用户的的id
        Long currentId = BaseContext.getCurrentId();

        //获得参数对象
        Object arg = args[0];

        //执行反射执行方法
        try {
            setId.invoke(arg, idWorker.nextId());
            setCreateTime.invoke(arg, LocalDateTime.now());
            setUpdateTime.invoke(arg, LocalDateTime.now());
            setUpdateUser.invoke(arg, currentId);
            setCreateUser.invoke(arg, currentId);
        } catch (Exception e) {
            throw new CustomException("反射执行方法失败");
        }
    }


    @Before("updatePointScut()")
    public void doUpdateBefore(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException {
        //获得方法的参数
        Object[] args = joinPoint.getArgs();
        Object arg = args[0];
        //通过反射获得方法的对象的class对象
        Class<?> aClass = arg.getClass();
        //通过反射获得对象的属性
        Field updateTime = aClass.getDeclaredField("updateTime");
        Field updateUser = aClass.getDeclaredField("updateUser");
        //通过暴力反射
        updateUser.setAccessible(true);
        updateTime.setAccessible(true);
        //通过反射为要增强的属性赋值
        updateUser.set(arg, BaseContext.getCurrentId());
        updateTime.set(arg, LocalDateTime.now());

    }
}
